Overview

The idea is to have 2 actions, one that execute the ExecuteAndWait action and another one that teminates the already running ExecuteAndWait action. The ExecuteAndWait action will needs to implement a Terminatable interface allowing it to be identified by the terminating action and hence be able to be informed to terminate itself through the terminate() method ( from Terminatable interface ).

XWork.xml configurations

<action name="longrunning" class="com.foo.frontend.action.test.LongRunningAction">
	<interceptor-ref name="defaultStack"/>		
	<interceptor-ref name="execAndWait"/>
	<result name="wait"    type="freemarker">/WEB-INF/content/action/test/longrunning/status.ftl</result>		
	<result name="error"   type="freemarker">/WEB-INF/content/action/test/longrunning/terminated.ftl</result>
	<result name="success" type="freemarker">/WEB-INF/content/action/test/longrunning/success.ftl</result>
</action> 	
<action name="terminatelongrunning" class="com.foo.frontend.action.test.TerminateLongRunningAction">
	<result name="success" type="freemarker">/WEB-INF/content/action/test/longrunning/terminatesuccess.ftl</result>
</action>

Action longruning will be the action executing the ExecuteAndWait action where as action terminatelongrunning will be the action to terminate the _ExecuteAndWait action.

Terminatable interface

public interface Terminatable
{
	public void terminate();
}

ExecuteAndWait action wish to be informed about its termination such that it could ends itself gracefully should implement this interface.

The ExecuteAndWait Action

public class LongRunningAction extends ActionSupport implements Terminatable
{
	private boolean terminated=false;
	private int i=0;
	
	public String execute()
	{
		while( i++ < 100 )
		{
			if( terminated )
			{
				return ERROR;
			}
			
			try
			{
				Thread.sleep(1000);
			}
			catch( InterruptedException ie )
			{
				// blah
			}
		}
		
		return SUCCESS;
	}
 
	public int getProgress()
	{
		return i;
	}
 
	public void terminate()
	{
		this.terminated = true;
	}
	
}

The ExecuteAndWait action is basically a conditional loop that loop indefintely until it's informed to ends itself by breaking the loop.

The action to terminate ExecuteAndWait action

import java.util.Map;
 
import com.opensymphony.webwork.interceptor.BackgroundProcess;
import com.opensymphony.webwork.interceptor.SessionAware;
import com.opensymphony.xwork.ActionSupport;
 
public class TerminateLongRunningAction extends ActionSupport implements SessionAware
{
	private String name = "__execWaitlongrunning";
	
	private Map session;
	
	public String execute()
	{
		BackgroundProcess bp = (BackgroundProcess) session.get( name );
		
		if( bp==null || bp.getAction()==null || !(bp.getAction() instanceof Terminatable) )
		{
			return ERROR;
		}
		
		Terminatable t = (Terminatable) bp.getAction();
		t.terminate();
		
		return SUCCESS;
	}
 
	public void setSession( Map session )
	{
		this.session = session;
	}
}

This action terminates the ExecuteAndWait action simply informing it through the terminate() method.

The freemarker pages

status.ftl
<html>
	<head>
		<title>Please wait</title>
		<meta http-equiv="refresh" content="1;url=<@ww.url includeParams="all" />"/>
	</head>
	<body>
		Progress: ${Session['__execWaitlongrunning'].action.progress}%	
	</body>
</html>
success.ftl
<html>
	<body>
		Exited normally.
	</body>
</html>
terminated.ftl
<html>
	<body>
		Terminated.
	</body>
</html>
termiantefailed.ftl
<html>
	<body>
		Process didn't exist or something like that.
	</body>
</html>
terminatesuccess.ftl
<html>
	<body>
		The background action was signalled to terminate.
	</body>
</html>

Special thanks to Lens that contributed this sollution in WebWork's forum